#include "AlgorithmLink_grid.h"
#include "../../../src_algorithms/src_slide/slide.h"

using namespace std;

//寻路
void AlgorithmLink_grid::routingRunBegin() {
	//netMap中有两个容器，0为竖线，x坐标逐条递增，对应寻路算法列号y；1为横线，y坐标逐条递增,对应寻路算法行号x
	vector<QPointF>& obsPts = m_data->m_Pts;
	vector<LineUI>& pinPairs = m_data->m_flyLines;
	int len_w = m_data->maxPt.x() + 1;
	int len_h = m_data->maxPt.y() + 1;
	len_w = m_data->maxPt.x() + 1;
	len_h = m_data->maxPt.y() + 1;
	//地图初始化
	m_ptArr.clear();
	for (int i = 0; i < len_w; ++i) {		//len_h为高度，对应二维数组的外层大小
		m_ptArr.emplace_back(vector<NodePoint>());
		for (int j = 0; j < len_h; ++j) {
			m_ptArr.back().emplace_back(NodePoint(i, j));
		}
	}
	for (auto& obsPt : obsPts) {
		m_ptArr[obsPt.x()][obsPt.y()].symbol = '#';	//设定障碍物标记
	}
	//引脚初始化
	m_Pins.clear();
	for (auto& pin : pinPairs) {
		m_Pins.emplace_back(make_pair(NodePoint(pin.x1(), pin.y1()), NodePoint(pin.x2(), pin.y2())));
		//m_Pins.emplace_back(make_pair(NodePoint(pin.y1(), pin.x1()), NodePoint(pin.y2(), pin.x2())));
	}
}
void AlgorithmLink_grid::routingRun(bool runInit, bool runPahtFinding) {
	if (!m_data) return;
	clock_t start_time = clock();
	//创建寻路器，禁布区预处理，寻路
	Router router(m_ptArr, m_Pins);				// 构造函数，获取地图数据（传递指针，读取文件已在进入该函数之前执行完毕）
	router.do_optimize_level = true;			// 是否执行节点优化
	router.do_post_processing = true;			// 是否执行后处理

	router.obs_init();			// 禁布区预处理

	clock_t mid_time = clock();
	if (runPahtFinding)
		router.main_router();		// 寻路
	clock_t end_time = clock();

	clock_t init_time = mid_time - start_time;
	clock_t find_path_time = end_time - start_time;
	cout << "PPDT run\n pre_time: " << init_time << " ms \trouting and post time: " << find_path_time << " ms" << endl;
	clock_t run_miniSeconds = static_cast<double>(end_time - start_time);
	setRoutingResultData(router);
}

//1.1 单根线段推挤
void AlgorithmLink_grid::pushLineRunBegin(LineUI& line, vector<LineUI>& lines) {
	m_selectLine = line;
	m_beginLines.clear();
	for (auto& line : lines) {
		double x1 = (double)line.x1(), y1 = (double)line.y1();
		double x2 = (double)line.x2(), y2 = (double)line.y2();
		m_beginLines.emplace_back(Line(Point(x1, y1), Point(x2, y2)));
	}
	if (m_beginLines.empty()) return;
	m_beginLines[0].Pt1.locked = true;
	m_beginLines.back().Pt2.locked = true;
	m_ui_wires = &lines;
}
bool AlgorithmLink_grid::pushLineRun(const QPointF& offset, const bool inGreed, const bool postOn) {
	if (!m_data) {
		cout << "pushLineRun: m_data is nullptr" << endl;
		return false;
	}
	//1.定义算法的输入数据
	vector<Line> polyLines_input;
	Line line_input;
	Point offset_input;
	//3.设置算法输入数据
	bool res = setPushLineData(polyLines_input, line_input, offset_input, offset);
	if (!res) return false;
	//4.创建推挤对象,设置基本参数
	SlideLine slide;
	int mode = 0;
	slide.setMode(mode);
	slide.setInGreed(inGreed);
	//5.执行算法
	int result = slide.pushSingleLine(polyLines_input, line_input, offset_input, postOn);
	//6.反馈给前端
	if (result == 0) {
		pushLineDataUpdate(polyLines_input);
		return true;
	}
	else {
		cout << "pushLineRun: pushSingleLine failed, error code= " << result << " ###" << endl;
		return false;
	}
	return true;
}

//1.3 Pin推挤pushOnePt
void AlgorithmLink_grid::pushPinRunBegin(QPointF pt, vector<LineUI>& lines) {
	m_selectPt = pt;
	m_beginLines.clear();
	for (auto& line : lines) {
		double x1 = (double)line.x1(), y1 = (double)line.y1();
		double x2 = (double)line.x2(), y2 = (double)line.y2();
		m_beginLines.emplace_back(Line(Point(x1, y1), Point(x2, y2)));
	}
	m_ui_wires = &lines;
}
bool AlgorithmLink_grid::pushPinRun(const QPointF& offset, bool inGreed) {
	if (!m_data) {
		cout << "pushPinRun: m_data is nullptr" << endl;
		return false;
	}
	//1.定义算法的输入数据
	vector<Line> polyLines_input;
	Point pt;
	Point offset_input;
	//3.设置算法输入数据
	bool res = setPushPinData(polyLines_input, pt, offset_input, offset);

	//4.创建推挤对象,设置基本参数m_config->m_onGrids, m_config->m_postOn
	SlideLine slide;
	int mode = 1;
	slide.setMode(mode);
	slide.setInGreed(inGreed);

	//5.执行算法
	int result = slide.pushOnePt(polyLines_input, pt, offset_input);

	//6.反馈给前端
	if (result == 0) {	//推中间点
		pushLineDataUpdate(polyLines_input);
		return true;
	}
	else if (result == 1) {	//推Pin,清空布线信息
		pushLineDataUpdate(polyLines_input);
		m_data->m_wires.clear();
		return true;
	}
	else {
		cout << "pushLineRun: pushSingleLine failed, error code= " << result << " ###" << endl;
		return false;
	}
	return true;

}

//私有函数
void AlgorithmLink_grid::setRoutingResultData(Router& router) {
	//将寻路结果数据传给m_data，以便前端显示
	std::vector<std::vector<NodePoint>> path_pts;			// 路径点（绘制的内容）3
	std::vector<std::vector<LinePtr>> tree_lines;			// 搜索树连线（绘制的内容）2
	std::vector<std::vector<LinePtr>> path_lines;			// 路径连线（绘制的内容）3
	std::vector<double> paths_lengths;
	//1.角点（绘制的内容）
	m_data->m_cornerPts.clear();
	for (auto& c_pt : router.m_cpts) {
		m_data->m_cornerPts.emplace_back(c_pt.first->x, c_pt.first->y);
	}

	//2.搜索树连线（绘制的内容）
	//for (int node_n : router.m_path_tree) {
	//	router.m_tree_lines.push_back(std::vector<LinePtr>());
	//	router.set_tree_lines(node_n);
	//	tree_lines.push_back(router.m_tree_lines.back());
	//}

	//4.路径连线（绘制的内容）
	m_data->m_wires.clear();
	for (int node_target_n : router.m_path) {
		Node* node = &router.m_nodes[node_target_n];
		std::vector<LineUI> path_lineUI;
		std::vector<LinePtr> path_line;
		while (node->m_parent_n != -1) {
			//当前节点与父节点连线
			Node* node_parent = &router.m_nodes[node->m_parent_n];
			path_lineUI.emplace_back(LineUI(node->m_ptr->x, node->m_ptr->y, node_parent->m_ptr->x, node_parent->m_ptr->y));
			path_line.emplace_back(LinePtr(node->m_ptr, node_parent->m_ptr));
			node = node_parent;
		}
		m_data->m_wires.emplace_back(path_lineUI);
		path_lines.emplace_back(path_line);
	}

	//6.计算路径长度
	for (auto& arr : path_lines) {
		double length = 0;
		if (arr.empty()) {
			paths_lengths.emplace_back(length);
			continue;
		}
		for (LinePtr& line : arr) {
			length += line.length();
		}
		paths_lengths.emplace_back(length);
	}

	//7. 路径总长度
	double total_length = 0;
	for (auto& length : paths_lengths) {
		total_length += length;
	}
	m_data->m_totalWireLength = total_length;
}
bool AlgorithmLink_grid::setPushLineData(vector<Line>& polyLines_input, Line& line_input, Point& offset_input, const QPointF& offset_ui) {
	bool zeroOffset = offset_ui.x() == 0 && offset_ui.y() == 0;
	if (zeroOffset || m_beginLines.empty()) return false;	//偏移量为0 或 输入数据为空，结束算法
	if (m_selectLine.length() == 0) return false;	//选取的线段为零线段，结束算法

	polyLines_input = vector<Line>(m_beginLines);
	line_input = Line(Point(m_selectLine.x1(), m_selectLine.y1()), Point(m_selectLine.x2(), m_selectLine.y2()));
	offset_input = Point(offset_ui.x(), offset_ui.y());
	return true;
}
void AlgorithmLink_grid::pushLineDataUpdate(vector<Line>& polyLines_input) {
	m_ui_wires->clear();
	for (auto& line : polyLines_input) {
		m_ui_wires->emplace_back(LineUI(line.Pt1.x, line.Pt1.y, line.Pt2.x, line.Pt2.y));
	}
}
bool AlgorithmLink_grid::setPushPinData(vector<Line>& polyLines_input, Point& pt_input, Point& offset_input, const QPointF& offset_ui) {
	polyLines_input = vector<Line>(m_beginLines);
	pt_input = Point(m_selectPt.x(), m_selectPt.y());
	offset_input = Point(offset_ui.x(), offset_ui.y());
	return true;
}
